from flask import Blueprint, render_template, request, jsonify, redirect, url_for, current_app
from flask_login import current_user, login_required
import os
from werkzeug.utils import secure_filename
from PIL import Image
import io
import base64

image_tools_bp = Blueprint('image_tools', __name__)

# 允许上传的图片格式
ALLOWED_IMAGE_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif', 'webp'}

def allowed_file(filename):
    """检查文件扩展名是否允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_IMAGE_EXTENSIONS

def convert_size(size_bytes):
    """将字节大小转换为人类可读格式"""
    if size_bytes < 1024:
        return f"{size_bytes} 字节"
    elif size_bytes < 1024 * 1024:
        return f"{size_bytes/1024:.2f} KB ({size_bytes} 字节)"
    else:
        return f"{size_bytes/(1024*1024):.2f} MB ({size_bytes} 字节)"

@image_tools_bp.route('/')
def index():
    tools = [
        {
            'name': '图片压缩',
            'slug': 'image-compress',
            'description': 'JPG/PNG图片压缩，保持高质量的同时减小体积',
            'icon': 'fa-compress-alt'
        },
        {
            'name': '图片格式转换',
            'slug': 'image-convert',
            'description': 'JPG、PNG、WEBP、GIF等格式互转',
            'icon': 'fa-exchange-alt'
        },
        {
            'name': '图片编辑',
            'slug': 'image-edit',
            'description': '裁剪、调整大小、添加水印等基础图片编辑功能',
            'icon': 'fa-crop-alt'
        }
    ]
    return render_template('tools/image/index.html', tools=tools)


@image_tools_bp.route('/image_compress', methods=['GET', 'POST'])
def image_compress():
    result = None
    original_size = None
    compressed_size = None
    
    if request.method == 'POST':
        if 'file' not in request.files:
            return redirect(request.url)
        
        file = request.files['file']
        if file.filename == '':
            return redirect(request.url)
        
        if file and allowed_file(file.filename):
            # 读取原始图片
            img_data = file.read()
            original_size = len(img_data)
            
            # 打开图片
            img = Image.open(io.BytesIO(img_data))
            
            # 获取压缩质量参数
            quality = int(request.form.get('quality', 80))
            
            # 压缩图片
            output = io.BytesIO()
            if img.format == 'PNG':
                img.save(output, format='PNG', optimize=True)
            else:  # 默认JPEG
                img.save(output, format='JPEG', quality=quality, optimize=True)
            
            compressed_data = output.getvalue()
            compressed_size = len(compressed_data)
            
            # 将结果编码为base64以便在页面上显示
            result = base64.b64encode(compressed_data).decode('utf-8')
    
    return render_template('tools/image/image_compress.html',
                          result=result,
                          original_size=original_size,
                          compressed_size=compressed_size)


@image_tools_bp.route('/image_convert', methods=['GET', 'POST'])
def image_convert():
    result = None
    original_format = None
    target_format = None
    
    if request.method == 'POST':
        if 'file' not in request.files:
            return redirect(request.url)
        
        file = request.files['file']
        if file.filename == '':
            return redirect(request.url)
        
        if file and allowed_file(file.filename):
            # 读取原始图片
            img_data = file.read()
            
            # 打开图片
            img = Image.open(io.BytesIO(img_data))
            original_format = img.format
            
            # 获取目标格式
            target_format = request.form.get('format', 'JPEG').upper()
            
            # 转换图片格式
            output = io.BytesIO()
            if target_format == 'JPEG':
                # 如果是JPEG，需要移除透明通道
                if img.mode in ('RGBA', 'LA'):
                    background = Image.new('RGB', img.size, (255, 255, 255))
                    background.paste(img, mask=img.split()[3])
                    img = background
                img.save(output, format='JPEG', quality=90)
            else:
                img.save(output, format=target_format)
            
            converted_data = output.getvalue()
            
            # 将结果编码为base64以便在页面上显示
            result = base64.b64encode(converted_data).decode('utf-8')
    
    return render_template('tools/image/image_convert.html',
                          result=result,
                          original_format=original_format,
                          target_format=target_format)


@image_tools_bp.route('/edit', methods=['GET', 'POST'])
def image_edit():
    """图片编辑页面"""
    if request.method == 'POST':
        # 检查是否有上传文件
        if 'file' not in request.files:
            return render_template('tools/image/image_edit.html', error='未上传文件')
        
        file = request.files['file']
        
        # 检查文件名
        if file.filename == '':
            return render_template('tools/image/image_edit.html', error='未选择文件')
        
        # 检查文件类型
        if not allowed_file(file.filename):
            return render_template('tools/image/image_edit.html', error='不支持的文件类型，仅支持jpg、png、gif和webp格式')
        
        try:
            # 读取原始图片
            img = Image.open(file)
            original_format = img.format
            
            # 获取原始尺寸
            original_width, original_height = img.size
            original_dimensions = f"{original_width} x {original_height} 像素"

            # 计算原始图片大小
            img_byte_arr = io.BytesIO()
            img.save(img_byte_arr, format=original_format if original_format else 'JPEG')
            original_size_bytes = img_byte_arr.tell()
            original_size = convert_size(original_size_bytes)
            
            # 获取编辑操作
            operation = request.form.get('operation', 'resize')
            
            # 处理图片
            if operation == 'resize':
                try:
                    width = request.form.get('width', '')
                    height = request.form.get('height', '')
                    
                    # 验证输入
                    if not width or not height:
                        return render_template('tools/image/image_edit.html', error='请输入有效的宽度和高度')
                    
                    width = int(width)
                    height = int(height)
                    
                    # 验证尺寸范围
                    if width <= 0 or height <= 0 or width > 5000 or height > 5000:
                        return render_template('tools/image/image_edit.html', error='尺寸必须在1至5000像素之间')
                    
                    # 调整图片大小
                    img = img.resize((width, height), Image.Resampling.LANCZOS)
                    current_app.logger.info(f'调整图片大小为 {width}x{height}')
                except ValueError as e:
                    return render_template('tools/image/image_edit.html', error=f'调整大小失败: {str(e)}')
                
            elif operation == 'crop':
                try:
                    # 获取裁剪区域
                    left = int(request.form.get('left', 0))
                    top = int(request.form.get('top', 0))
                    right = int(request.form.get('right', original_width))
                    bottom = int(request.form.get('bottom', original_height))
                    
                    # 验证裁剪区域
                    if left < 0 or top < 0 or right > original_width or bottom > original_height:
                        return render_template('tools/image/image_edit.html', error='裁剪区域超出原始图片范围')
                    
                    if left >= right or top >= bottom:
                        return render_template('tools/image/image_edit.html', error='无效的裁剪区域，请确保右下角坐标大于左上角坐标')
                    
                    # 裁剪图片
                    img = img.crop((left, top, right, bottom))
                    current_app.logger.info(f'裁剪图片区域: ({left}, {top}, {right}, {bottom})')
                except ValueError as e:
                    return render_template('tools/image/image_edit.html', error=f'裁剪失败: {str(e)}')
                
            elif operation == 'rotate':
                try:
                    # 获取旋转角度
                    angle = float(request.form.get('angle', 90))
                    
                    # 执行旋转，使用白色背景
                    img = img.rotate(-angle, Image.Resampling.BICUBIC, expand=True, fillcolor=(255, 255, 255, 0))
                    current_app.logger.info(f'旋转图片角度: {angle}度')
                except ValueError as e:
                    return render_template('tools/image/image_edit.html', error=f'旋转失败: {str(e)}')
            
            # 获取处理后的图片尺寸
            edited_width, edited_height = img.size
            edited_dimensions = f"{edited_width} x {edited_height} 像素"
            
            # 保存处理后的图片到内存
            output = io.BytesIO()
            
            # 如果是透明PNG并且要保存为JPEG，需要添加白色背景
            if img.mode == 'RGBA' and (original_format == 'JPEG' or original_format is None):
                background = Image.new('RGB', img.size, (255, 255, 255))
                background.paste(img, mask=img.split()[3])  # 3 is the alpha channel
                background.save(output, format='JPEG', quality=95)
            else:
                # 使用原始格式保存，如果原始格式未知则使用JPEG
                save_format = original_format if original_format else 'JPEG'
                if save_format == 'JPEG':
                    img = img.convert('RGB')
                    img.save(output, format=save_format, quality=95)
                else:
                    img.save(output, format=save_format)
            
            # 计算处理后的图片大小
            edited_size_bytes = output.tell()
            edited_size = convert_size(edited_size_bytes)
            
            # 将图片转为base64
            output.seek(0)
            encoded_img = base64.b64encode(output.getvalue()).decode('utf-8')
            
            return render_template('tools/image/image_edit.html', 
                                   result=encoded_img, 
                                   original_size=original_size, 
                                   edited_size=edited_size,
                                   original_dimensions=original_dimensions,
                                   edited_dimensions=edited_dimensions)
            
        except Exception as e:
            current_app.logger.error(f'图片编辑失败: {str(e)}')
            return render_template('tools/image/image_edit.html', error=f'处理图片时出错: {str(e)}')
    
    return render_template('tools/image/image_edit.html') 